package com.seaside.park.api;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.seaside.common.bean.Privilege;
import com.seaside.common.bean.Result;
import com.seaside.common.service.UserService;
import com.seaside.park.util.AliyunOSSUtil;
import com.seaside.parkCommon.bean.User;
import com.seaside.parkCommon.bean.VerifyCode;
import com.seaside.parkCommon.mapper.UserMapper;
import com.seaside.parkCommon.service.SmsService;
import com.seaside.parkCommon.service.VerifyCodeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.security.core.Authentication;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;


@Slf4j
@Api(tags = "用户管理")
@RestController
@RequestMapping("/api/user")
public class UserAPI {

    @Autowired
    private UserMapper usermapper;

    @Autowired
    private AliyunOSSUtil ossUtil;

    @Autowired
    private SmsService smsService;

    @Autowired
    private VerifyCodeService verifyCodeService;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${weixin.appId}")
    private String appId;

    @Value("${weixin.secret}")
    private String secret;

    /**
     * 发送手机验证码
     *
     * @param mobile
     * @return
     */
    @PostMapping("/sms/{mobile}")
    public Result smsVerifyCode(@PathVariable("mobile") String mobile) {
        VerifyCode verifyCode = verifyCodeService.getVerifyCode(mobile);
        Result result = smsService.sendMobileCode(mobile, "yourOutId", verifyCode.getVerifyCode());
        Map map = new HashMap();
        map.put("codeId", verifyCode.getId());
        result.setData(map);
        return result;
    }

    /**
     * 通过手机验证码修改密码
     *
     * @param mobile
     * @param newPassword
     * @param codeId
     * @param code
     * @return
     */
    @PostMapping("/modifyPwdByCode")
    public Result modifyPwdByCode(@RequestParam("mobile") String mobile,
                                  @RequestParam("newPassword") String newPassword,
                                  @RequestParam("codeId") String codeId,
                                  @RequestParam("code") String code) {
        Result result = verifyCodeService.verify(codeId, code, mobile);
        if (result.isSucess()) {
            Map<String, Object> map = new HashMap<>();
            map.put("user_tel", mobile);
            List<User> users = usermapper.selectByMap(map);
            UserService.selectUserByPhone(mobile);
            if (users == null) {
                Result.Error("手机号未注册或已被禁用");
            }
            if (users.size() > 1) {
                Result.Error("手机号码绑定多个用户，无法修改");
            }
            User user = users.get(0);
            // 明文密码修改
            user.setPwd(newPassword);
            usermapper.updateById(user);
            // oauth密码修改
            if (UserService.updatePassWord(newPassword, user.getUserName())) {
                return Result.OK("修改成功");
            } else {
                return Result.Error("修改失败");
            }
        } else {
            return result;
        }
    }

    @ApiOperation(value = "注销用户", response = Result.class)
    @ApiImplicitParams({@ApiImplicitParam(paramType = "header", name = "bearer", dataTypeClass = String.class, required = true, value = "用户token"),})
    @PostMapping("/logoff")
    public Result<User> info(@ApiIgnore Authentication auth) {

        log.debug("### 【Auth】 =>" + JSON.toJSONString(auth));

        User user = usermapper.selectById(auth.getName());
        user.setDel(true);
        usermapper.updateById(user);
        if (UserService.updateIsDel(user.getUserName(), true)) {
            return Result.OK("注销成功");
        } else {
            return Result.Error("注销失败");
        }
    }

    @ApiOperation(value = "用户注册", response = Result.class)
    @ApiImplicitParams({@ApiImplicitParam(paramType = "query", name = "username", dataTypeClass = String.class, required = true,
            value = "用户名（唯一）"), @ApiImplicitParam(paramType = "query", name = "password", dataTypeClass = String.class, required = true,
            value = "用户密码", defaultValue = "666666"), @ApiImplicitParam(paramType = "query", name = "phone", dataTypeClass = String.class, required = true,
            value = "用户电话"), @ApiImplicitParam(paramType = "query", name = "sex", dataTypeClass = Integer.class, required = true,
            value = "用户性别0:男 1:女", defaultValue = "0")})
    @PostMapping("/reg")
    public Result reg(String username, String password, String phone, int sex) {
        String userGuid = null;
        try {
            //注册oauth2认证服务器
            com.seaside.common.bean.User authUser = new com.seaside.common.bean.User(username, password, phone, "");
            //移动用户
            authUser.privileges().add(Privilege.MOBILE);
            userGuid = UserService.addUser(authUser);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            return Result.Error(ex.getMessage());
        }

        //成功注册oauth服务器
        if (null != userGuid) {
            User user = new User();
            user.setUserGuid(userGuid);
            user.setUserName(username);
            user.setUserSex(sex);
            user.setUserTel(phone);
            user.setUserType("user");
            user.setPwd(password);
            usermapper.insert(user);
        } else {
            return Result.Error("添加失败");
        }
        return Result.OK("添加成功");
    }

    @ApiOperation(value = "一键登录", response = Result.class)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "code", dataTypeClass = String.class, required = true, value = "用户凭证"),
            @ApiImplicitParam(paramType = "query", name = "phone", dataTypeClass = String.class, required = true, value = "用户电话"),})
    @PostMapping("/login")
    public Result login(@RequestParam String loginCode, @RequestParam String phoneCode) {
        String userGuid = null;
        String originPwd = "666666";
        String phone = "";
        try {
            // 接着获取access_token
            ResponseEntity<String> response = restTemplate.exchange(
                    "https://api.weixin.qq.com/cgi-bin/token?" +
                            "grant_type=client_credential" +
                            "&appid=" + appId +
                            "&secret=" + secret,
                    HttpMethod.GET,
                    null,
                    String.class
            );
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode responseBody = objectMapper.readTree(response.getBody());
            String accessToken = responseBody.path("access_token").asText();
            // 获取手机号
            HttpResponse<String> stringHttpResponse = Unirest.post("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken)
                    .header("Content-Type", "application/json")
                    .header("Accept", "*/*")
                    .header("Host", "api.weixin.qq.com")
                    .header("Connection", "keep-alive")
                    .body("{\"code\": \"" + phoneCode + "\"}")
                    .asString();
            objectMapper = new ObjectMapper();
            responseBody = objectMapper.readTree(stringHttpResponse.getBody());
            phone = responseBody.path("phone_info").path("phoneNumber").asText();
            System.out.println(stringHttpResponse.getBody());
            if(Objects.equals(phone, "")){
                return Result.Error("手机号码获取失败：" + stringHttpResponse.getBody());
            }
            System.out.println("当前手机号：" + phone);
        } catch (JsonProcessingException e) {
            return Result.Error("微信鉴权错误：" + e.getMessage());
        }
        User user = usermapper.selectOne(new QueryWrapper<User>().eq("user_tel", phone));
        // 不存在当前用户
        if (user == null || Objects.equals(user.getUserGuid(), "")) {
            try {
                //注册oauth2认证服务器
                com.seaside.common.bean.User authUser = new com.seaside.common.bean.User(phone, originPwd, phone, "");
                //移动用户
                authUser.privileges().add(Privilege.MOBILE);
                userGuid = UserService.addUser(authUser);
            } catch (Exception ex) {
                log.error(ex.getMessage(), ex);
                return Result.Error(ex.getMessage());
            }
            //成功注册oauth服务器
            if (null != userGuid) {
                user = new User();
                user.setUserGuid(userGuid);
                user.setUserName(phone);
                user.setUserSex(0);
                user.setUserTel(phone);
                user.setUserType("user");
                user.setPwd(originPwd);
                usermapper.insert(user);
            } else {
                return Result.Error("添加失败");
            }
        }
        // 调用 OAuth 服务器获取 token
        String url = "https://mobile.aowo.vip/spring-oauth-server/oauth/token";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("grant_type", "password");
        body.add("scope", "all");
        body.add("client_id", "mobile-client");
        body.add("client_secret", "mobile");
        body.add("username", phone);
        body.add("password", user.getPwd());
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        if (response.getStatusCode().is2xxSuccessful()) {
            try {
                JsonNode rootNode = new ObjectMapper().readTree(response.getBody());
                Map<String, Object> data = new HashMap<>();
                data.put("access_token", rootNode.get("access_token").asText());
                data.put("refresh_token", rootNode.get("refresh_token").asText());
                data.put("scope", rootNode.get("scope").asText());
                data.put("user_guid", rootNode.get("user_guid").asText());
                data.put("token_type", rootNode.get("token_type").asText());
                data.put("expires_in", rootNode.get("expires_in").asInt());
                return Result.OK("添加成功", data);
            } catch (Exception e) {
                return Result.Error("添加失败: 解析响应失败");
            }
        } else {
            return Result.Error("添加失败: 无法获取 OAuth token");
        }
    }

    @ApiOperation(value = "获取用户信息", response = Result.class)
    @ApiImplicitParams(
            {@ApiImplicitParam(paramType = "header", name = "bearer", dataTypeClass = String.class, required = true, value = "用户token"), @ApiImplicitParam(
                    paramType = "query", name = "clientId", dataTypeClass = String.class, required = false, value = "app端获取的cid")})
    @PostMapping("/info")
    public Result<User> info(@ApiIgnore Authentication auth, String clientId) {

        log.debug("### 【Auth】 =>" + JSON.toJSONString(auth));

        User user = usermapper.selectById(auth.getName());
        //更新用户最新的clientId
        if (StringUtils.isNotBlank(clientId)) {
            user.setClientId(clientId);
            usermapper.updateById(user);
        }
        Result<User> result = Result.OK("查询成功");
        user.setPwd("");
        result.setData(user);
        return result;
    }

    @ApiOperation(value = "修改用户密码", response = Result.class)
    @ApiImplicitParams(
            {@ApiImplicitParam(paramType = "header", name = "bearer", dataTypeClass = String.class, required = true, value = "用户token"), @ApiImplicitParam(
                    paramType = "query", name = "newPassword", dataTypeClass = String.class, required = true, value = "MultipartFile图片文件")})
    @PostMapping("/modifyPwd")
    public Result modifyPwd(@ApiIgnore Authentication auth, String newPassword) {
        if (UserService.updatePassWord(newPassword, auth.getName())) {
            return Result.OK("密码修改成功!");
        } else {
            return Result.Error("密码修改失败!");
        }
    }

    @ApiOperation(value = "修改用户头像", response = Result.class)
    @ApiImplicitParams(
            {@ApiImplicitParam(paramType = "header", name = "bearer", dataTypeClass = String.class, required = true, value = "用户token"), @ApiImplicitParam(
                    paramType = "query", name = "file", dataTypeClass = MultipartFile.class, required = true, value = "MultipartFile图片文件")})
    @PostMapping("/modifyIcon")
    public Result modifyIcon(@ApiIgnore Authentication auth, @RequestParam("file") MultipartFile file) {
        User user = usermapper.selectById(auth.getName());
        try {
            String uploadUrl = ossUtil.uploadImg2Oss(file);
            user.setUserIcon(ossUtil.getImgUrl(uploadUrl));
            usermapper.updateById(user);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            return Result.OK("修改失败！");
        }
        return Result.OK("修改成功！");
    }

    @ApiOperation(value = "修改用户欢迎语音，生日日期", response = Result.class)
    @ApiImplicitParams(
            {@ApiImplicitParam(paramType = "header", name = "bearer", dataTypeClass = String.class, required = true, value = "用户token"), @ApiImplicitParam(
                    paramType = "query", name = "welcomeText", dataTypeClass = String.class, required = true, value = "欢迎语音"), @ApiImplicitParam(
                    paramType = "query", name = "birthday", dataTypeClass = String.class, required = true, value = "业主生日")})
    @PostMapping("/update")
    public Result modifyIcon(User user, @ApiIgnore Authentication auth) {
        try {
            user.setUserName(auth.getName());
            usermapper.updateById(user);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            return Result.OK("修改失败！");
        }
        return Result.OK("修改成功！");
    }
}
